package io.renren.modules.backstage.controller;
import com.alibaba.nacos.client.utils.StringUtils;
import io.renren.common.utils.LiveUtils;
import io.renren.common.utils.Result;
import io.renren.modules.backstage.entity.CameraBean;
import io.renren.modules.backstage.entity.CameraThread;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@RestController
@RequestMapping("backstage/live")
public class CameraVideoController {

    private static Log log = LogFactory.getLog(CameraVideoController.class);
    /*
     * 保存已经开始推的流 streamMap
     */
    public static Map<String, CameraBean> STREAMMAP = new ConcurrentHashMap<>();

    @Value("${push.host:127.0.0.1}")
    private String pushHost;
    @Value("${push.port:1935}")
    private String pushPort;

    // 存放任务 线程
    public static Map<String, CameraThread.MyRunnable> JOBMAP = new HashMap<>();

    @ApiOperation(value = "开启视频流")
    @RequestMapping(value = "/openVideo", method = RequestMethod.POST)
    @RequiresPermissions("backstage:live:openVideo")
    public Result openVideo(@RequestBody @Valid CameraBean vo) {
        if (!LiveUtils.isTrueIp(vo.getCameraIp())) {
            return Result.fail("ip格式输入错误");
        }
        // 获取当前时间
        String openTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date().getTime());
        Set<String> keys = STREAMMAP.keySet();
        // 当推流map为空时才让进入转封装，避免资源不够
        if (0 == keys.size()) {
            // 开始推流
            String token = UUID.randomUUID().toString();
            String IP = LiveUtils.IpConvert(vo.getCameraIp());
            String url = "";

            // 直播流
            String rtsp = "rtsp://" + vo.getCameraAccount() + ":" + vo.getCameraPassword() + "@" + IP + ":554/cam/realmonitor?channel=1&subtype=0";
            String rtmp = "rtmp://" + LiveUtils.IpConvert(pushHost) + ":" + pushPort + "/live/" + token;

            vo.setRtsp(rtsp);
            vo.setRtmp(rtmp);
            vo.setOpenTime(openTime);
            vo.setToken(token);
            vo.setCount(1);


            // 先验证ip是否能连接成功，避免后续推流失败
            Socket rtspSocket = new Socket();
            Socket rtmpSocket = new Socket();

            // 建立TCP Scoket连接，超时时间1s *3
            try {
                rtspSocket.connect(new InetSocketAddress(vo.getCameraIp(), 554), 1000*3);
            } catch (IOException e) {
                e.printStackTrace();
                log.error("与拉流IP：" + vo.getCameraIp() + " 建立TCP连接失败！");
                return Result.data(500,vo,"与拉流IP：" + vo.getCameraIp() +" 建立TCP连接失败！");
            }

            try {
                rtmpSocket.connect(new InetSocketAddress(LiveUtils.IpConvert(pushHost),Integer.parseInt(pushPort)), 1000*3);
            } catch (IOException e) {
                e.printStackTrace();
                log.error("与推流IP：   " + pushHost + "   端口： " + pushPort + " 建立TCP连接失败！");
                return Result.data(500,vo,"与推流IP：" + pushHost  +" 建立TCP连接失败,请检查nginx服务");
            }
            // 执行任务
            CameraThread.MyRunnable task = new CameraThread.MyRunnable(vo);
            CameraThread.MyRunnable.threadPool.execute(task);
            JOBMAP.put(token, task);

        }
        return Result.data(200,vo.getRtmp(),"成功！");
    }

    @ApiOperation(value = "关闭视频流")
    @RequestMapping(value = "/closeVideo/{token}", method = RequestMethod.GET)
    @RequiresPermissions("backstage:live:closeVideo")
    public Result closeVideo(@PathVariable("token") String token) {
        if (StringUtils.isNotEmpty(token)) {
            if (JOBMAP.containsKey(token) && STREAMMAP.containsKey(token)) {
                if (0 < STREAMMAP.get(token).getCount()) {
                    // 人数-1
                    STREAMMAP.get(token).setCount(STREAMMAP.get(token).getCount() - 1);
                    CameraVideoController.JOBMAP.get(token).setInterrupted(token);
                    log.info("关闭成功 当前相机使用人数为" + STREAMMAP.get(token).getCount() + " [ip："+ STREAMMAP.get(token).getCameraIp() +" rtmp:" + STREAMMAP.get(token).getRtmp() + "]");
                    return Result.success("关闭成功");
                }
            }
        }
        return Result.fail("请检查该token下的视频是否开启成功");
    }
}
